/*
 * Copyright (c) 2005, 2014 vacoor
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 */
package org.vacoor.nothing.common.util;

import java.text.StringCharacterIterator;
import java.util.*;

/**
 * 字符串工具类
 *
 * @author vacoor
 */
public abstract class StringUtils {
    public static final String EMPTY_STRING = "";

    /**
     * 给定字符序列是否有长度
     *
     * @param charseq
     * @return
     */
    public static boolean hasLength(CharSequence charseq) {
        return charseq != null && charseq.length() > 0;
    }

    /**
     * 给定字符序列是否包含非空白字符
     *
     * @param charseq
     * @return
     */
    public static boolean hasText(CharSequence charseq) {
        int len;
        if (charseq == null || (len = charseq.length()) == 0) {
            return false;
        }

        for (int i = 0; i < len; i++) {
            if (!Character.isWhitespace(charseq.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * 允许负数索引 (最后一个元素索引为 -1)
     *
     * @param str
     * @param start
     * @param end
     * @return
     */
    public static String slice(String str, int start, int end) {
        if (!hasLength(str)) {
            return str;
        }

        int len = str.length();
        start = start < 0 ? start + len : start;
        end = end < 0 ? end + len : end;
        return start > end ? EMPTY_STRING : str.substring(start, end);
    }


    /**
     * 首字母大写
     *
     * @param str
     * @return
     */
    public static String capitalize(String str) {
        if (!hasLength(str)) {
            return str;
        }

        char[] chars = str.toCharArray();
        chars[0] = Character.toUpperCase(chars[0]);
        return new String(chars);
    }

    /**
     * 取消首字母大写
     * 如果前两个字符都是大写字母, 则不转换
     */
    public static String uncapitalize(String str) {
        if (!hasLength(str)) {
            return str;
        }

        // 如果前两个字符都是大写则不转换
        if (str.length() > 1 && Character.isUpperCase(str.charAt(0)) && Character.isUpperCase(str.charAt(1))) {
            return str;
        }

        char[] chars = str.toCharArray();
        chars[0] = Character.toLowerCase(chars[0]);
        return new String(chars);
    }

    /**
     * 反转大小写
     *
     * @param str
     * @return
     */
    public String swapCase(String str) {
        if (hasLength(str)) {
            return str;
        }

        char[] chars = str.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char c = chars[i];
            if (Character.isLowerCase(c)) {
                chars[i] = Character.toUpperCase(c);
            } else if (Character.isUpperCase(c)) {
                chars[i] = Character.toLowerCase(c);
            } else if (Character.isTitleCase(c)) {
                chars[i] = Character.toLowerCase(c);
            }
        }
        return new String(chars);
    }


    public static String trim(String str) {
        return str == null ? null : str.trim();
    }


    /**
     * left trim
     *
     * @param str
     * @return
     */
    public static String ltrim(String str) {
        if (!hasLength(str)) {
            return str;
        }

        int st = 0;
        final int len = str.length();
        for (; st < len && str.charAt(st) <= ' '; st++) ;
        return st > 0 ? str.substring(st, len) : str;
    }

    public static String rtrim(String str) {
        if (!hasLength(str)) {
            return str;
        }

        final int st = 0;
        int len = str.length();
        for (; st < len && str.charAt(len - 1) <= ' '; len--) ;
        return len < str.length() ? str.substring(st, len) : str;
    }

    public static String pad(String str, char padChar, int total, boolean lpad) {
        int len = str.length();
        if (len >= total) {
            return str;
        }

        StringBuilder buff = new StringBuilder();
        for (int i = 0; i < total - len; i++) {
            buff.append(padChar);
        }

        if (lpad) {
            buff.append(str);
        } else {
            buff.insert(0, str);
        }
        return buff.toString();
    }

    public static String trimToNull(String str) {
        final String trim = trim(str);
        return !hasLength(trim) ? null : trim;
    }

    public static String trimToEmpty(String str) {
        final String trim = trim(str);
        return trim == null ? EMPTY_STRING : trim;
    }


    /**
     * 下划线写法 --> 驼峰写法
     *
     * @param str
     * @param firstCharUpperCase 是否首字母大写
     * @return
     */
    public static String underscoreToCamelCase(String str, boolean firstCharUpperCase) {
        return delimitedToCamelCase(str, '_', firstCharUpperCase);
    }

    /**
     * 特定分隔符 --> 驼峰写法
     *
     * @param str
     * @param delimiter
     * @param firstCharUpperCase
     * @return
     */
    public static String delimitedToCamelCase(String str, char delimiter, boolean firstCharUpperCase) {
        if (!hasLength(str)) {
            return str;
        }

        StringCharacterIterator it = new StringCharacterIterator(str.toLowerCase(Locale.ENGLISH));
        StringBuilder segment = new StringBuilder(str.length());
        boolean undlerline = false;
        for (; it.getIndex() < it.getEndIndex(); it.next()) {
            char c = it.current();
            if ((0 == it.getIndex() && firstCharUpperCase) || undlerline) {
                segment.append(Character.toUpperCase(c));
                undlerline = false;
            } else if (delimiter == c) {
                undlerline = true;
            } else {
                segment.append(c);
            }
        }

        return segment.toString();
    }

    /**
     * 驼峰写法 --> 下划线写法
     *
     * @param str
     * @return
     */
    public static String camelCaseToUnderscore(String str, boolean upperCase) {
        if (!hasLength(str)) {
            return str;
        }

        char[] chars = str.toCharArray();
        StringBuilder segment = new StringBuilder();
        segment.append(upperCase ? Character.toUpperCase(chars[0]) : Character.toLowerCase(chars[0]));

        for (int i = 1; i < chars.length; i++) {
            char c = chars[i];
            // 大写字母后不是大写字母且不是下划线则追加
            if (Character.isUpperCase(c) && i + 1 < chars.length && !Character.isUpperCase(chars[i + 1]) && '_' != chars[i + 1]) {
                segment.append('_');
            }
            c = upperCase ? Character.toUpperCase(c) : Character.toLowerCase(c);
            segment.append(c);
        }

        return segment.toString();
    }
    /*
    public static String unqualifiedClassName(Class type) {
        if (type.isArray()) {
            return unqualifiedClassName(type.getComponentType())+"Array";
        }
        String name = type.getName();
        return name.substring(name.lastIndexOf('.')+1);
    }
    */

    public static String clean(String in) {
        String out = in;

        if (in != null) {
            out = in.trim();
            if (out.equals(EMPTY_STRING)) {
                out = null;
            }
        }

        return out;
    }

    /**
     * 清理字符串数组中 null / "", 始终返回一个字符串数组
     *
     * @param array
     * @return
     */
    public static String[] clean(String[] array) {
        if (array == null) {
            return new String[0];
        }
        List<String> result = new ArrayList<String>(array.length);
        for (String s : array) {
            if (hasLength(s)) {
                result.add(s);
            }
        }
        return result.toArray(new String[result.size()]);
    }


    public static <T> String join(T[] array, String separator) {
        if (null == array) {
            return null;
        }

        separator = separator != null ? separator : EMPTY_STRING;

        StringBuilder buff = new StringBuilder();
        for (int i = 0; i < array.length; i++) {
            if (i > 0) {
                buff.append(separator);
            }

            buff.append(array[i]);
        }

        return buff.toString();
    }

    public static Iterable<String> tokenize(String s) {
        return tokenize(new StringTokenizer(s));
    }

    public static Iterable<String> tokenize(String s, String separators) {
        final StringTokenizer tokenizer = new StringTokenizer(s, separators);
        return new Iterable<String>() {
            @Override
            public Iterator<String> iterator() {
                return new Iterator<String>() {
                    @Override
                    public boolean hasNext() {
                        return tokenizer.hasMoreTokens();
                    }

                    @Override
                    public String next() {
                        return tokenizer.nextToken();
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    public static Iterable<String> tokenize(final StringTokenizer tokenizer) {
        return new Iterable<String>() {

            @Override
            public Iterator<String> iterator() {
                return new Iterator<String>() {
                    @Override
                    public boolean hasNext() {
                        return tokenizer.hasMoreTokens();
                    }

                    @Override
                    public String next() {
                        return tokenizer.nextToken();
                    }

                    @Override
                    public void remove() {
                        throw new UnsupportedOperationException();
                    }
                };
            }
        };
    }

    private StringUtils() {
    }
}
